/**
 * TypeScript definitions for account data structures
 * These types mirror the Python schema definitions in the backend
 */

export type PositionSchema = {
  vt_position_id: string;
  trade_app_name: string;
  gateway_name: string;
  symbol: string;
  product_type: string;
  exchange: string;
  direction: string;
  volume: number;
  frozen: number;
  cost: number;
  price: number;
  pnl: number;
  yd_volume: number;
  margin: number;
  last_price: number;
  last_update_time: string;
  pnl_by_cost: number;
  option_market_value: number;
  option_intrinsic_value: number;
  option_time_value: number;
  option_underlying_last_price: number;
  // refdata
  underlying_symbol: string;
  strike_price: number;
  iv: number;
  delta: number;
  gamma: number;
};

export type AccountSchema = {
  trade_app_name: string;
  gateway_name: string;
  account_id: string;
  balance: number;
  frozen: number;
  available: number;
  last_update_time: string;
};

export type AccountInfoSchema = {
  trade_app_name: string;
  gateway_name: string;
  account_id: string;
  account_name: string;
  account: AccountSchema;
  // key is vt_position_id
  positions: Map<string, PositionSchema>;
  // key is vt_order_id
  orders: Map<string, OrderSchema>;
  // key is vt_trade_id
  trades: Map<string, TradeSchema>;
  // key is risk report name
  risk_reports: Map<string, RiskReportSchema>;
  logs: LogSchema[];
  totalPnl?: number;
  totalOptionMarketValue?: number;
  totalOptionTimeValue?: number;
  totalMarketValue?: number;
  last_update_time: string;
};

export type OrderSchema = {
  trade_app_name: string;
  gateway_name: string;
  symbol: string;
  exchange: string;
  order_id: string;
  order_type: string;
  direction: string | null;
  offset: string;
  price: number;
  volume: number;
  traded: number;
  status: string;
  event_time: string | null;
  reference: string;
  vt_symbol: string;
  vt_order_id: string;
  is_active: boolean;
};

export type TradeSchema = {
  trade_app_name: string;
  gateway_name: string;
  symbol: string;
  exchange: string;
  order_id: string;
  trade_id: string;
  direction: string;
  offset: string;
  price: number;
  volume: number;
  event_time: string | null;
  vt_symbol: string;
  vt_order_id: string;
  vt_trade_id: string;
};

export type RiskReportSchema = {
  name: string;
  template: string;
  arguments: Record<string, any>;
  report: string;
  gateway_name: string;
  trade_app_name: string | null;
  time: string | null;
};

export type AccountAggregationSchema = {
  event_id: string;
  // key is gateway_name
  aggregation: Map<string, AccountInfoSchema>;
};

// Types comes from backend
export type AccountAggregationSchemaObject = {
  event_id: string;
  aggregation: Record<
    // key: gateway_name
    string,
    {
      trade_app_name: string;
      gateway_name: string;
      account_id: string;
      account_name: string;
      account?: AccountSchema | null;
      positions: Record<
        // key: vt_position_id
        string,
        PositionSchema
      >;
      orders: Record<
        // key: vt_order_id
        string,
        OrderSchema
      >;
      trades: Record<
        // key: vt_trade_id
        string,
        TradeSchema
      >;
      risk_reports: Record<
        // key: name
        string,
        RiskReportSchema
      >;
      logs: LogSchema[];
      last_update_time: string;
    }
  >;
};

/**
 * Transforms backend record-based data structure to Map-based structure
 * @param data The data from the backend in record/object format
 * @returns Transformed data with Maps for accounts and positions
 */
export function convertToMapStructure(
  data: AccountAggregationSchemaObject
): AccountAggregationSchema {
  const result: AccountAggregationSchema = {
    event_id: data.event_id,
    aggregation: new Map<string, AccountInfoSchema>()
  };

  // Convert flat object keyed by gateway_name to Map structure
  Object.entries(data.aggregation).forEach(([gatewayName, accountInfo]) => {
    // Create empty AccountSchema if account field is null/undefined
    const accountSnapshot: AccountSchema = accountInfo.account ?? {
      trade_app_name: accountInfo.trade_app_name,
      gateway_name: gatewayName,
      account_id: accountInfo.account_id,
      balance: 0,
      frozen: 0,
      available: 0,
      last_update_time: accountInfo.last_update_time
    };

    const positionsMap = new Map<string, PositionSchema>();
    const ordersMap = new Map<string, OrderSchema>();
    const tradesMap = new Map<string, TradeSchema>();
    const riskReportsMap = new Map<string, RiskReportSchema>();

    // positions
    if (accountInfo.positions) {
      Object.entries(accountInfo.positions).forEach(([positionId, position]) =>
        positionsMap.set(positionId, position)
      );
    }

    // orders
    if (accountInfo.orders) {
      Object.entries(accountInfo.orders).forEach(([orderId, order]) =>
        ordersMap.set(orderId, order)
      );
    }

    // trades
    if (accountInfo.trades) {
      Object.entries(accountInfo.trades).forEach(([tradeId, trade]) =>
        tradesMap.set(tradeId, trade)
      );
    }

    // risk reports
    if (accountInfo.risk_reports) {
      Object.entries(accountInfo.risk_reports).forEach(([name, report]) =>
        riskReportsMap.set(name, report)
      );
    }

    result.aggregation.set(gatewayName, {
      trade_app_name: accountInfo.trade_app_name,
      gateway_name: gatewayName,
      account_id: accountInfo.account_id,
      account_name: accountInfo.account_name,
      account: accountSnapshot,
      positions: positionsMap,
      orders: ordersMap,
      trades: tradesMap,
      risk_reports: riskReportsMap,
      logs: accountInfo.logs ?? [],
      last_update_time: accountInfo.last_update_time
    });
  });

  return result;
}

export interface PositionAnalysisSchema {
  underlying_symbol: string;
  product_type?: string;
  symbol?: string;
  direction?: string;
  volume?: number;
  cost?: number;
  last_price?: number;
  pnl_by_cost: number;
  delta: number;
  // aggregated gamma grouped by direction on summary rows
  long_gamma?: number;
  short_gamma?: number;
  option_market_value: number;
  option_intrinsic_value: number;
  option_time_value: number;
  option_underlying_last_price?: number;
  is_summary_row?: boolean;
}

export interface PositionAnalysisGroupSchema extends PositionAnalysisSchema {
  children: PositionAnalysisSchema[];
}

export interface LogSchema {
  trade_app_name: string;
  gateway_name: string;
  source: string;
  msg: string;
  level: number;
  time: string;
}
